#ifndef __SERVER__
#define __SERVER__

#include <iostream>
#include <string>
#include <cstdio>
#include <jsoncpp/json/json.h>
#include "httplib.h"
#include "TableVideo.hpp"
#include "FileTool.hpp"
#include "JsonTool.hpp"
#include "Log.hpp"
namespace SERVER
{
    using namespace LOGSpace;
    //./www/video/
    const static std::string WWWROOT = "/home/ubuntu/Lhd/video-on-demand-project/Source/www";
    const static std::string Video = "/video/";
    const static std::string Image = "/image/";
    class Server
    {
    public:
        Server(int port) : _port(port) {}
        ~Server() {}
        bool RunModule()
        {
            // Table_control::Table_Video::GetInstacne()->;
            // 创建资源目录
            FILETOOL::FileTool(WWWROOT).CreateDir(); // 创建资源根目录
            std::string video_real_path = WWWROOT + Video;
            std::string image_real_path = WWWROOT + Image;
            FILETOOL::FileTool(video_real_path).CreateDir(); // 创建视频资源目录
            FILETOOL::FileTool(image_real_path).CreateDir(); // 创建视频图片目录
            // 设置静态根目录
            _server.set_mount_point("/", WWWROOT);
            // 建立请求---处理映射关系
            _server.Post("/video", Insert);
            _server.Put("/video/(\\d+)", Update);
            _server.Delete("/video/(\\d+)", Delete);
            _server.Get("/video/(\\d+)", SelectOnce);
            _server.Get("/video/", SelectALL);
            // 启动服务器
            _server.listen("0.0.0.0", _port);
            return true;
        }

    private:
        // 业务处理
        static void Insert(const httplib::Request &req, httplib::Response &resp)
        {
            if (!req.has_file("name") || !req.has_file("info") || !req.has_file("video") || !req.has_file("image"))
            {
                LOG(FATAL, "file is not exist!\n");
                resp.status = 400;
                resp.body = R"({"result":false, "reason":"上传的文件信息错误！"})";
                resp.set_header("Content-Type", "application/json");
                return;
            }
            httplib::MultipartFormData name = req.get_file_value("name");
            httplib::MultipartFormData info = req.get_file_value("info");
            httplib::MultipartFormData video = req.get_file_value("video"); // 视频文件
            httplib::MultipartFormData image = req.get_file_value("image"); // 封面文件
            // 视频名称
            std::string videoname = name.content;
            // 获取上传的视频的简介
            std::string videoinfo = info.content;
            // 获取URL
            std::string videopath = WWWROOT + Video + videoname + video.filename; //./www/video/蜘蛛侠蜘蛛侠.mp4
            std::string imagepath = WWWROOT + Image + videoname + image.filename; //./www/image/蜘蛛侠蜘蛛侠.jpg
            // 创建对应文件
            if (!FILETOOL::FileTool(videopath).SetContent(video.content))
            {
                LOG(FATAL, "set video content failed!\n");
                resp.status = 500;
                resp.body = R"({"result":false, "reason":"视频文件存储失败！"})";
                resp.set_header("Content-Type", "application/json");
                return;
            }

            if (!FILETOOL::FileTool(imagepath).SetContent(image.content))
            {
                LOG(FATAL, "set image content failed!\n");
                resp.status = 500;
                resp.body = R"({"result":false, "reason":"视频图片文件存储失败！"})";
                resp.set_header("Content-Type", "application/json");
                return;
            }
            // 写入数据库
            Json::Value video_json;
            video_json["name"] = videoname;
            video_json["info"] = videoinfo;
            video_json["video"] = Video + videoname + video.filename; // /video/xxx
            video_json["image"] = Image + videoname + image.filename; // /image/xxx

            if (!Table_control::Table_Video::GetInstacne()->Insert(video_json))
            {
                LOG(FATAL, "database use failed!\n");
                resp.status = 500;
                resp.body = R"({"result":false, "reason":"数据库操作失败！"})";
                resp.set_header("Content-Type", "application/json");
                return;
            }
        }
        static void Delete(const httplib::Request &req, httplib::Response &resp)
        {
            // 1.获取要删除的视频文件的id
            int video_id = std::stoi(req.matches[1]);
            // 获取对应id的视频在数据库中的信息
            Json::Value video;
            if (!Table_control::Table_Video::GetInstacne()->SelectOnce(video_id, &video))
            {
                resp.status = 500;
                resp.body = R"({"result":false,"reason":"该视频不存在！"})";
                resp.set_header("Content-Type", "application/json");
                return;
            }
            // 获取视频文件路径
            std::string video_path = WWWROOT + video["video"].asString();
            // 获取封面图片文件路径
            std::string image_path = WWWROOT + video["image"].asString();
            // 删除文件数据
            remove(video_path.c_str());
            remove(image_path.c_str());
            // 删除数据库的视频属性
            if (!Table_control::Table_Video::GetInstacne()->Delete(video_id))
            {
                resp.status = 500;
                resp.body = R"({"result":false,"reason":"该视频属性在数据库中不存在!"})";
                resp.set_header("Content-Type", "application/json");
                return;
            }
        }
        static void Update(const httplib::Request &req, httplib::Response &resp)
        {
            // 1.获取要删除的视频文件的id
            int video_id = std::stoi(req.matches[1]);
            // 更新数据库中的信息
            Json::Value video;
            if (!JSONTOOL::JsonTool::DelSerialization(&video, req.body))
            {
                resp.status = 400;
                resp.body = R"({"result":false,"reason":"新的视频信息格式解析失败!"})";
                resp.set_header("Content-Type", "application/json");
                return;
            }
            if (!Table_control::Table_Video::GetInstacne()->Update(video_id, video))
            {
                resp.status = 400;
                resp.body = R"({"result":false,"reason":"视频属性更新失败!"})";
                resp.set_header("Content-Type", "application/json");
                return;
            }
        }
        static void SelectOnce(const httplib::Request &req, httplib::Response &resp)
        {
            // 1.获取要删除的视频文件的id
            int video_id = std::stoi(req.matches[1]);
            Json::Value video;
            if (!Table_control::Table_Video::GetInstacne()->SelectOnce(video_id, &video))
            {
                resp.status = 400;
                resp.body = R"({"result":false,"reason":"未查询到指定视频信息"})";
                resp.set_header("Content-Type", "application/json");
                return;
            }
            // 序列化
            if (!JSONTOOL::JsonTool::Serialization(video, &resp.body))
            {
                resp.status = 400;
                resp.body = R"({"result":false,"reason":"视频信息格式解析失败!"})";
                resp.set_header("Content-Type", "application/json");
                return;
            }
            resp.set_header("Content-Type", "application/json");
            return;
        }
        static void SelectALL(const httplib::Request &req, httplib::Response &resp)
        {
            // 首先判断是否是模糊搜索
            bool is_Fuzzy_matche = false; // 默认是全部查询
            Json::Value videos;
            std::string serach_key;
            if (req.has_param("search"))
            {
                is_Fuzzy_matche = true;
                serach_key = req.get_param_value("search");
            }
            if (is_Fuzzy_matche)
            {
                // 模糊搜索
                if (!Table_control::Table_Video::GetInstacne()->SelectLike(serach_key, &videos))
                {
                    resp.status = 400;
                    resp.body = R"({"result":false,"reason":"关键字搜索错误!"})";
                    resp.set_header("Content-Type", "application/json");
                    return;
                }
            }
            else
            {
                // 全部查询
                if (!Table_control::Table_Video::GetInstacne()->SelectAll(&videos))
                {
                    resp.status = 400;
                    resp.body = R"({"result":false,"reason":"搜索错误!"})";
                    resp.set_header("Content-Type", "application/json");
                    return;
                }
            }
            // 序列化
            if (!JSONTOOL::JsonTool::Serialization(videos, &resp.body))
            {
                resp.status = 400;
                resp.body = R"({"result":false,"reason":"视频信息格式解析失败!"})";
                resp.set_header("Content-Type", "application/json");
                return;
            }
            resp.set_header("Content-Type", "application/json");
            return;
        }

    private:
        int _port;               // 监听的端口号
        httplib::Server _server; // 服务器
    };
}
#endif
